MetaFile MetaFiles! Form1, DrawJet Click Me! Picture1 SaveMeta Save Meta LoadMeta Load Meta PrintMeta Print Meta AboutBox About... Command1 Command1_Click^ CreateMetaFile rectangle% CloseMetaFile PlayMetaFile Picture1 testmetaW Form_Click; printer7 Ellipse SetMapMode MM_ANISOTROPIC SetWindowExt SetViewPortExt{ scalewidth ScaleHeight SetWindowOrg MM_TWIPS MM_ISOTROPIC width heightW BeginPaint lpPaint PAINTSTRUCT! pstruct Rectp ferase{ rcpaint@ fRestoreE fincupdate rgbReserved Left` right botomj frestorL MetafilehWnd Form1 rectang6 GetFocusT GetClientRectN lpRect bottomd scalemode MetaRectangle gMdc( MetaEllipse` Command2_Click9 MetaCircle Radius NotUsed Startt Finisht Aspect Command3_Click GetDeviceCaps TEXTCAPS@ TC_CR_ANY CURVECAPS CC_NONE CC_CIRCLES CC_PIE CC_CHORD) CC_ELLIPSES CC_WIDE CC_STYLED CC_WIDESTYLED| CC_INTERIORSk MetaFile LC_POLYLINE LINECAPSf MetaArcw MetaLine MetaMove MetaLineFrom Picture1_Click Form_Resize @ Form_Load MetaInitializeU PicBox picboz ctlname Visible FALSE SaveMeta_Click0 MetaSaveFile` MetaFileName MFFileName LoadMeta_Clickp MetaLoadFile MetaFile_ReSize Resize DeleteMetafile FileNum, CreatePen nPenStyle nWidth crColor PS_SOLID SelectObject= HExtc DrawMore_Click OldPen RedPenI BluePen& GreenPenZ BlackPen FirstOldPen; DeleteObject| hMdcq OriginalPen PrintMeta_Click DrawJet_Click MM_TEXTq MetaText LOGFONT lfHeight lfWidth lfEscapementL lfOrientation0 lfWeight lfItalic lfUnderline? lfStrikeOut lfCharSet^ lfOutPrecision lfClipPrecision~ lfQuality lfPitchAndFamily lfFaceName LF_FACESIZE CreateFontIndirectI lpLogFont~ FontType OldFont MetaFill FloodStyle FloodColor FloodHatch7 BorderColorY BS_HATCHED HS_DIAGCROSS BrushType lbStyle# lbColor lbHatch FloodFill Brush CreateBrushIndirect OldBrush screen scalewith\ mousepointerM Form_UnloadI Cancel OEM_CHARSET FW_BOLD PROOF_QUALITY VARIABLE_PITCHr FF_MODERN FW_NORMAL FIXED_PITCH FF_ROMAN szFaceName retval GetTextFace FF_SWISSc fontsR currentyH currentx FF_DONTCAREy FF_DECORATIVEn WindowState AboutBox_Click Credits MetaRecordStart MetaRecordStop$ XScale YScale fYScale fXScale ffYScale+ ffXScale sizeb MetaLineStep Currently notice picture3 correctF routine hardcoded Picture1_Paint The code in this module plays a metafile when picture1 is resized.. A jet is drawn with a maximum with (including borders) of 1400 and a maximum height of 1600. (These are scaled with the fXScale% and the fYScale%). We are still having some problems making certain function operate correctly and we have noted these problems in the code with sample code commented out.t Currently, you will notice that the picture can't replay itself back to the correct size with out the play routine knowing what it's dimensions are.. They are hardcoded in our demo. If you know what our problem is, please let us know.b Also, the flood fill routine is buggy. (ie: UAE!) This wouldu be a great addition, if it worked. Another bug is when I try to reselect the original objects (in the DrawJet event). UAE!! Also, if you intend to draw an ellipse, use the MetaCircle function, not the MetaArc function. The arc won't draw correctly (esp on the PostScript printer) if youu have start=0 radians and finish=2*pi radians. Form_Resize This event handler takes care of actually playing the metafile onto the screen. Don't do anything if the form is minimized. Must have scalemode set to pixels.x MapMode is like setting the VB scale properties. We are generally concerned with only two MapModes at this point; either MM_ANISOTROPIC or MM_ISOTROPIC. For ourr purposes, all they do is set how the X axis relates to the Y axis. If you set it to MM_ANISOTROPIC then the Y axis and X axis can be scaled independently. If you set it to MM_ANISOTROPIC then the Y axis will always be dependent on the X axis.a In other words, if you double the X dimension, the Y dimension will also double.u This is useful if you want to insure that a circle always looks like a circle instead of an ellipse, etc. Setting the WindowExt is part of the way you tell windows how to scale your drawing.w Your drawing should be relative to the window extent you define. Window extentst are in logical units. We suggest that you make them at least as large as your screen. We have a 1024x768 screen so we set the Window extent to 1400 x 1600.1 Notice that we've scaled the window extent with the fXScale% and fYScale% factors that we define in the DrawJet routine. This way you can easily experiment with changing the Window Extent while maintaining the correct proportions for ther jet drawing. This sets the origin of the window to 0,0. This is like setting ScaleLeft andt ScaleTop. Next we wanted to find the ScaleWidth and ScaleHeight of the picture boxe so we could make the drawing as large as would fit. Unfortunately, when we used the ScaleWidth and ScaleHeight properties those values seemed to bet slightly off from what we needed. Instead we called the api GetClientRect()e for the picture box. Then next three steps perform this task.e The last step before actually playing the metafile is to set the viewport extent. By always setting it to the inside dimensions of the picture box, we insure that the jet metafile will always be played as large as the picture box will hold. Finally, this next statement causes the jet drawing to be displayed.a SaveMeta_Click This routine saves the metafile to disk in the SDK metafile format. Enter the file name" Meta-Save" LoadMeta_Click This routine takes care of loading loading a metafile from disk.. Enter the file name" Meta-Load" Load Failed" Meta-load" PrintMeta_Click This routine takes care of playing the metafile to the printer. Notice that thee steps involved are almost identical to the steps used for playing the metafile to the screen. We simply substituted Printer.hdc for Picture1.hdc.. Must use pixels for GDI calls0 DrawJet_Click Define the pens that will be used. These don't need to beh in the metafile itself. Pens are used for defining color line width, etc.i These following instructions are not used because we couldn't get the floodfill function to work. Therefore they are commented out.t BrushType.lbStyle = BS_HATCHED BrushType.lbColor = RGB(10, 20, 30)0 BrushType.lbHatch = HS_DIAGCROSS Brush% = CreateBrushIndirect(BrushType) OldBrush% = SelectObject(gMdc%, Brush%) When a metafile is drawn, its dimensions are dependent on the logical size of the original drawing, the logical units of the window in which the object will be drawn (theh Window extent), and the device units of the drawing surface in the window (the Viewport extent). When the metafile is played (drawn) to the picture box the original size of the drawing is measured relative to the window extent. So, for example, ife you draw a horizontal line that is 10 units long and the window extent of the picturec box is 10 units wide, then the line will extend the entire width of the picture box. Both the length of the line and the window extent of the picture box are in logicalg units. If you enlarge or decrease the actual size of the picture box, it is still 10 units wide and the line will still extend across its entire length. The third important measurement is the viewport extent. The size of this measuremente is in device units (always use Pixels). If, now, the size of the drawing, the windowi extent, and the viewport extent are all equal to 10, then we would have a very small 10 pixel x 10 pixel window containing a horizontal line. If the viewport is increased,a (i.e., by enlarging the size of the picture box), then the size of the line will also increase proportionally. If the window extent is increased to 20, then the length oft the line will appear to shrink to 1/2 the width of the picture box. From our experiments, it seems best to set the Window extent to values larger than the size of the screen (in pixels) and then scale the drawing commands accordingly. Remembere that the size of the object you draw will be relative to the Window extent. This createse a problem if the Window extent is too small. If you draw a vertical line when the horizontal window extent is a small number, such as 10, you are saying in a sense that the entire window width is only 10 units wide. If the viewport extent is something like 100 pixels, then it takes 10 pixels to make up one logical unit. If a vertical is 1 unit wide, it is actually 10 pixels wide. Thus the line would appear very thick. If you always set the window extent to a value larger than the screen dimensions (in pixels) you) will never have this problem.b In this routine we do the drawing. We set the window and viewport extents in then code for the form_resize event.v Initialize the process of recording the meta file. This needs to be done everytimey before drawing a metafile. Draw Wings And Nose of the jet. Note that all units are in pixels and the origin isi at the upperleft of the picture box. gMdc% is the Device Context for the metafile. It was created in the call to MetaRecordStart(). It was meant to be hidden for all ofl our drawing commands, but it is still needed for some of the windows api calls that wea haven't wrapped yet. SelectObject is such a api function. It is used to make thee specified object current. In the following case it is making the BluePen% the currentr pen for the metafile. This is analogous to setting the forecolor property. Our first drawing command is the MetaMove command. It is analogous to the PSet method. The MetaLineStep drawing command is analogous to the VB Line method when using theg Step qualifier. In other words, it draws a line from the current location, established with the MetaMove command, to the point passed in the parameters. These lines will all be drawn in Blue since we selected the BluePen% object above.b Draw Tail Draw it with the Black pen. The MetaLine command is analogous to the VB Line method when not using the Step qualifier. It draws a line from one point to the other. Note, though that ita does not include that ending point as part of the line. This is different than the VB line method. This is a good area for improvement later. Draw Canopy Use green to draw the canopy. The MetaArc function is analogous to the Circle method when drawing only a part of the circle. We have had some problems with this function on PostScriptc printers. The fifth and sixth parameters specify the start and end of the arce in terms of radians. If we set the start to 0 and the end to 2 * PI, then we get a circle on our HP Laser Jet, but nothing on our PostScript. Therefore, we don't recommend using the command for drawing full circles. Use the MetaCircle command instead.t Draw Weapons Pylons on the wingsl Use the red pen for the pylons. The MetaRectangle command is analogous to the Line method with the B parameter. Just specify the coordinates of the upper left corner as the first twot parameters and the lower right corner as the las two parameters.s Draw rotated text on the wing. We struggled with rotated text for a long time, but thanks to a solution uploaded to Compuserve by Ted Young we have it working. This same technique will work with the standard print method to a picture box. It seems our main problem was in using the CreateFont api function. When we switched to the CreateFontIndirect api instead, it worked.r To print text to a metafile you first need to define the font using the api LOGFONT structure which we have declared here with the variable FontType. It didn't seem that any of the members of this structure were self explanatory. We experimented a lot to get what we want. We got rotation to work only when wee had the lfCharSet and lfPitchAndFamily members set exactly as you see them. It would work with different values on the printer, but not on the screen. The actual rotation is defined with the lfEscapement member. Set it to a value inu tenths of a degree. In other words 900 (90 * 10) is 90 degrees rotation. Modern This is the angle in tenths of a degree) FontType.lfItalic As String * 1 FontType.lfUnderline As String * 1 FontType.lfStrikeOut As String * 1 FontType.lfOutPrecision As String * 1 FontType.lfClipPrecision As String * 1 Now that we have defined the font it's time to actually create it.e Finally SelectObject makes our newly created font the current font. And the MetaText wrapper function actuall writes the text to theo metafile. Flood Fill the Canopy (can't get this to work...) This is one area we are still having problems with. Maybe someone else will have a suggestion. Following is the code that we couldn't get to work. The result was a UAE. b% = MetaFill(70, 60, RGB(0, 255, 0)) OldPen% = SelectObject(gMdc%, OriginalPen%) OldBrush% = SelectObject(gMdc%, OldBrush%) Finally, we are done with the drawing. We need to do some housecleaning nowg to close the metafile. This is all taken care of with the MetaRecordStop wrapper routine.t Delete the pens & fonts to free the resources If Brush% <> 0 Then b% = DeleteObject(Brush%)% So far all that we have done is create a metafile in memory someplace that contains all of our drawing commands. Nothing has appeared on the screen ore the printer so far. Making the drawing appear on the screen or printer ise called "playing the metafile."e The code that plays back the metafile is in the resize event. Form_Unload AboutBox_Click Command1_Click Form_Load For this demo, we have defined an X and Y scale factor which affects both the size of thee drawing and the size of the window extents. By varying these values fXScale% and fYScale% you can see how it affects the picture.n Picture1_Paint